home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / memory / xmem10 / xmem.asm < prev    next >
Assembly Source File  |  1995-03-25  |  22KB  |  754 lines

  1. ;-----------------------------------------------------------------------
  2. ;Can't take credit for the ASM code here, found it on a local BBS.
  3. ;The author has beem lost in the mists of time.
  4. ;
  5. .MODEL MEDIUM
  6.  
  7.  
  8.         EXTmemError     EQU     7
  9.         XMSmemError     EQU     8
  10.  
  11.  
  12.         ShortAdr        EQU     0
  13.         LongAdr         EQU     1
  14.  
  15.  
  16. procname        MACRO  Pnam
  17.         PUBLIC  _&Pnam&
  18. _&Pnam&  PROC    FAR
  19. ENDM
  20.  
  21. endproc         MACRO  Pnam
  22.  
  23. _&Pnam&  ENDP
  24.  
  25. ENDM
  26.  
  27. pwrlolvl_TEXT   SEGMENT WORD PUBLIC 'CODE'
  28.  
  29.         ASSUME  CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT
  30.  
  31. SUBTTL  (Local Procedure) XMS_setup - find a XMS driver.
  32. PAGE+
  33.  
  34.                 EVEN
  35. XMSwordByte     LABEL BYTE
  36. XMSword         DW      0
  37.  
  38. XMSmoveSTRUC    STRUC
  39.  
  40. Length          DW      0
  41. LengthX         DW      0
  42. SrcHandle       DW      0
  43. SrcOffset       DW      0
  44. SrcOffsetX      DW      0
  45. DestHandle      DW      0
  46. DestOffset      DW      0
  47. DestOffsetX     DW      0
  48.  
  49. XMSmoveSTRUC    ENDS
  50.  
  51. XMSmainGET      XMSmoveSTRUC  <>
  52. XMSmainPUT      XMSmoveSTRUC  <>
  53. XMSwordGET      XMSmoveSTRUC  <2,,,,,,OFFSET XMSword>
  54. XMSwordPUT      XMSmoveSTRUC  <2,,,OFFSET XMSword>
  55.  
  56. XMSfunctAdr     DW      0, 0
  57.  
  58.  
  59. ; Don't try to call this from your programs
  60.  
  61. XMS_setup               PROC NEAR
  62.  
  63.         PUSH    DS
  64.         PUSH    ES
  65.         PUSH    BX
  66.  
  67.         MOV     AX,CS                   ; Set Data segment to the code
  68. segment.
  69.         MOV     DS,AX                   ;
  70.         MOV     [XMSwordGET.DestOffsetX],AX  ; Set up the move data
  71. structures.
  72.         MOV     [XMSwordPUT.SrcOffsetX],AX   ;
  73.  
  74.         MOV     AX,4300H                ; See if a XMS Driver Exists.
  75.         INT     2FH                     ;
  76.         CMP     AL,80H                  ;
  77.         MOV     AX,0                    ;
  78.         JNE     XMS_setup01             ; Return 0 if not.
  79.  
  80.         MOV     AX,4310H                ; If so, set the driver's function
  81.         INT     2FH                     ;  address.
  82.         MOV     [XMSfunctAdr],BX        ;
  83.         MOV     [XMSfunctAdr+2],ES      ;
  84.  
  85.         MOV     AX,1                    ; Return 1.
  86.  
  87.   XMS_setup01:
  88.         POP     BX
  89.         POP     ES
  90.         POP     DS
  91.  
  92.         RET
  93.  
  94. XMS_setup               ENDP
  95.  
  96.  
  97. SUBTTL  LSHL - Shift an unsigned long left
  98. PAGE+
  99.  
  100.  ;****************************************************************************
  101.  ;* 
  102.  ;* Shift an unsigned long integer left n number of bits.
  103.  ;*
  104.  ;****************************************************************************
  105.  
  106.  ;
  107.  ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n
  108. );
  109.  ;
  110.  
  111. LSHLparms STRUC
  112.  
  113.         DW      0, 0
  114.         DW      0
  115. SHLadr   DD      ?
  116. SHLn     DW      ?
  117.  
  118. LSHLparms ENDS
  119.  
  120. procname  LSHL
  121.  
  122.         PUSH    BP
  123.         MOV     BP,SP
  124.  
  125.         PUSH    BX
  126.         PUSH    CX
  127.         PUSH    DX
  128.  
  129.         PUSH    DS
  130.         LDS     BX,SHLadr[BP]
  131.         MOV     CX,SHLn[BP]
  132.  
  133.         MOV     AX,[BX]                 ; Get the long integer.
  134.         MOV     DX,[BX+2]               ; 
  135.  
  136.  LSHL_01:
  137.         SHL     AX,1                    ; Do the long shift.
  138.         RCL     DX,1                    ; 
  139.         LOOP    LSHL_01                 ; 
  140.  
  141.         MOV     [BX],AX                 ; Replace the addressed number.
  142.         MOV     [BX+2],DX               ; 
  143.  
  144.         POP     DS
  145.         POP     DX
  146.         POP     CX
  147.         POP     BX
  148.  
  149.         POP     BP
  150.         RET                             ; Exit
  151.  
  152. endproc   LSHL
  153.  
  154.  
  155. SUBTTL  Extended Memory - Stack template for EXTget, EXTput
  156. PAGE+
  157.  
  158. EXTgpparms STRUC
  159.  
  160.         DW      0, 0
  161.         DW      0
  162. extgpBase    DW      ?
  163. extgpblk     DW      ?
  164. extgpblkAdr  DW      ?
  165. extgpBytes   DW      ?
  166. extgpmemAdr  DW      ?
  167.              DW      ?
  168.  
  169. EXTgpparms ENDS
  170.  
  171.  
  172.  
  173. SUBTTL  Extended Memory - XMS - Return total XMS memory.
  174. PAGE+
  175.  
  176.  ; Use this function to detect wether or not XMS driver installed
  177.  ;
  178.  ; Stack frame definition for unsigned XMS_available( void );
  179.  ;
  180.  ;  The total XMS memory available (in 16k blocks) is returned.
  181.  ;
  182. procname  XMS_available
  183.  
  184.         PUSH    BX
  185.         PUSH    CX
  186.         PUSH    DX
  187.  
  188.         CALL    XMS_setup               ; Ensure XMS memory is set.
  189.         TEST    AX,AX                   ;
  190.         JZ      XMS_available01         ; Return zero if not.
  191.  
  192.         MOV     AH,08H                  ; Set the size function code.
  193.         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
  194.         TEST    AX,AX                   ;
  195.         JZ      XMS_available01         ;
  196.  
  197.         MOV     AX,DX                   ; Set available Kbytes.
  198.         SUB     AX,64                   ; Subtract out the HMA (HIMEM.SYS
  199. bug).
  200.         JNC     XMS_available01         ;
  201.         XOR     AX,AX                   ; Set zero if underflow.
  202.  
  203.   XMS_available01:
  204.         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
  205.         SHR     AX,CL                   ;
  206.  
  207.         POP     DX
  208.         POP     CX
  209.         POP     BX
  210.  
  211.         RET                             ; Exit
  212.  
  213. endproc   XMS_available
  214.  
  215. SUBTTL  Extended Memory - XMS - Return largest block XMS mem.
  216. PAGE+
  217.  
  218.  ;
  219.  ; Stack frame definition for unsigned XMSblk_available( void );
  220.  ;
  221.  ;  The size of the largest block of XMS memory available,
  222.  ;  (in 16Kbyte blocks) is returned.
  223.  ;
  224. procname  XMSblk_available
  225.  
  226.         PUSH    BX
  227.         PUSH    CX
  228.         PUSH    DX
  229.  
  230.         CALL    XMS_setup               ; Ensure XMS memory is set.
  231.         TEST    AX,AX                   ;
  232.         JZ      XMSblk_available01      ; Return zero if not.
  233.  
  234.         MOV     AH,08H                  ; Set the size function code.
  235.         CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
  236.         TEST    AX,AX                   ;
  237.         JZ      XMSblk_available01      ;
  238.  
  239.         SUB     DX,64                   ; Subtract out the HMA (HIMEM.SYS
  240. bug).
  241.         JNC     XMSblk_available0X      ;
  242.         XOR     DX,DX                   ; Set zero if underflow.
  243.  
  244.  XMSblk_available0X:
  245.         CMP     AX,DX                   ;
  246.         JBE     XMSblk_available01      ;
  247.         MOV     AX,DX                   ; Set available Kbytes.
  248.  
  249.   XMSblk_available01:
  250.         MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
  251.         SHR     AX,CL                   ;
  252.  
  253.         POP     DX
  254.         POP     CX
  255.         POP     BX
  256.  
  257.         RET                             ; Exit
  258.  
  259. endproc   XMSblk_available
  260.  
  261. SUBTTL  Extended Memory - XMS De-allocate a memory block.
  262. PAGE+
  263.  
  264.  ;
  265.  ; Stack frame definition for int XMS_dealloc( int Hdl );
  266.  ;
  267.  ; Zero is returned if the operation fails, non-zero if success.
  268.  ;
  269.  ; its really important to do this, only other way to recover
  270.  ; XMS blocks is to re-boot
  271.  
  272. XMSdealparms STRUC
  273.  
  274.         DW      0, 0
  275.         DW      0
  276. xmsdealHdl  DW      ?
  277.  
  278. XMSdealparms ENDS
  279.  
  280.  
  281. procname  XMS_dealloc
  282.  
  283.         PUSH    BP
  284.         MOV     BP,SP
  285.  
  286.         PUSH    BX
  287.         PUSH    DX
  288.  
  289. ;        CALL    XMS_setup               ; Ensure XMS memory is set.
  290. ;        TEST    AX,AX                   ;
  291. ;        JZ      XMS_dealloc01           ; Return zero if not.
  292.  
  293.         MOV     DX,xmsdealHdl[BP]       ; Get the handle to de-allocate.
  294.         MOV     AH,0AH                  ;
  295.  
  296.         CALL    DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.
  297.  
  298.   XMS_dealloc01:
  299.         POP     DX
  300.         POP     BX
  301.  
  302.         POP     BP
  303.         RET                             ; Exit
  304.  
  305. endproc   XMS_dealloc
  306.  
  307. SUBTTL  Extended Memory - XMS Allocate a memory block.
  308. PAGE+
  309.  
  310.  ;
  311.  ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );
  312.  ;
  313.  ;     rsrved and size are in 16K byte blocks.
  314.  ;     rsrved is mem set aside for EMS, generaly zero
  315.  ;
  316.  ;  Zero is returned if the operation fails.
  317.  ;  Block (XMS) handle is returned if success.
  318.  ;
  319.  ;  size - is reduced by the amount of XMS memory actually allocated.
  320.  ;
  321.  
  322. XMSalparms STRUC
  323.  
  324.         DW      0, 0
  325.         DW      0
  326. xmsalrsrvd DW      ?
  327. xmsalsize  DD      ?
  328.  
  329. XMSalparms ENDS
  330.  
  331. procname  XMS_alloc
  332.  
  333.         PUSH    BP
  334.         MOV     BP,SP
  335.  
  336.         PUSH    BX
  337.         PUSH    CX
  338.         PUSH    DX
  339.         PUSH    DI
  340.         PUSH    ES
  341.         PUSH    DS
  342.  
  343.         MOV     AX,CS                   ; Set the data segment to the code
  344.         MOV     DS,AX                   ;  segment.
  345.  
  346.         MOV     CX,4                    ;
  347.         ADD     xmsalrsrvd[BP],CX       ; Subtract out the HMA (HIMEM.SYS
  348. bug).
  349.         SHL     xmsalrsrvd[BP],CL       ; Convert reserved blocks to K-bytes.
  350.  
  351.         LES     DI,xmsalsize[BP]        ; Load size address.
  352.         XOR     AX,AX                   ;
  353.         MOV     BX,ES:[DI]              ; Get the requested size in blocks.
  354.  
  355.         TEST    BX,0F000H               ; Check for more than 64 Megabytes.
  356.         JZ      XMS_alloc01             ;
  357.         MOV     BX,00FFFH               ;
  358.  
  359.   XMS_alloc01:
  360.         MOV     CL,4                    ;
  361.         SHL     BX,CL                   ; Convert to K-Bytes.
  362.         MOV     CX,BX                   ; In CX.
  363.         JZ      XMS_alloc05             ; Return zero if no size requested.
  364.  
  365. ;        CALL    XMS_setup               ; Ensure XMS memory is set.
  366. ;        TEST    AX,AX                   ;
  367. ;        JZ      XMS_alloc05             ; Return zero if not.
  368.  
  369.         XOR     BX,BX                   ;
  370.         MOV     AH,08H                  ; Set to Query Free XMS Memory.
  371.         CALL    DWORD PTR [XMSfunctAdr] ;
  372.  
  373.         SUB     DX,xmsalrsrvd[BP]       ; Subtract out reserved blocks.
  374.         JB      XMS_alloc03             ; Ensure no borrow.
  375.         CMP     AX,DX                   ;
  376.         JBE     XMS_alloc02             ;
  377.         MOV     AX,DX                   ;
  378.  
  379.   XMS_alloc02:
  380.         MOV     DX,AX                   ;
  381.         CMP     AX,68                   ; Ensure enough memory to allocate.
  382.  
  383.   XMS_alloc03:
  384.         MOV     AX,0                    ;
  385.         JB      XMS_alloc05             ; Exit if not.
  386.  
  387.         CMP     BL,80H                  ; Check for errors.
  388.         JE      XMS_alloc05             ;
  389.         CMP     BL,81H                  ;
  390.         JE      XMS_alloc05             ;
  391.  
  392.         CMP     CX,DX                   ; Check actual against requested size.
  393.         JBE     XMS_alloc04             ;
  394.         MOV     CX,DX                   ; Set if actual < requested.
  395.  
  396.   XMS_alloc04:
  397.         MOV     DX,CX                   ; Set requested size.
  398.         MOV     AH,09H                  ;
  399.         CALL    DWORD PTR [XMSfunctAdr] ; Allocate it.
  400.         DEC     AX                      ; Check for errors.
  401.         MOV     AX,0                    ;
  402.         JNZ     XMS_alloc05             ;
  403.  
  404.  
  405.         MOV     AX,CX                   ; Convert allocated size in KBytes
  406.         MOV     CL,4                    ; to allocated blocks.
  407.         SHR     AX,CL                   ;
  408.  
  409.         SUB     ES:[DI],AX              ; Subtract the blocks allocated.
  410.         MOV     AX,DX                   ; Set to return the handle.
  411.  
  412.   XMS_alloc05:
  413.         POP     DS
  414.         POP     ES
  415.         POP     DI
  416.         POP     DX
  417.         POP     CX
  418.         POP     BX
  419.  
  420.         POP     BP
  421.         RET                             ; Exit
  422.  
  423. endproc  XMS_alloc
  424.  
  425. SUBTTL  Extended Memory - XMS get, put Stack Frame definition
  426. PAGE+
  427.  
  428.  
  429. XMSgpparms STRUC
  430.  
  431.         DW      0, 0
  432.         DW      0
  433. xmsgpHdl     DW      ?
  434. xmsgpblk     DW      ?
  435. xmsgpblkAdr  DW      ?
  436. xmsgpBytes   DW      ?
  437. xmsgpmemAdr  DD      ?
  438.  
  439. XMSgpparms ENDS
  440.  
  441. SUBTTL  Extended Memory - XMStoMem
  442. PAGE+
  443.  
  444.  
  445.  ;
  446.  ; Stack frame definition for int XMStoMem( unsigned Handle,
  447.  ;                                          unsigned blk,
  448.  ;                                          unsigned blkAdr,
  449.  ;                                          unsigned Bytes,
  450.  ;                                          char     *memAdr
  451.  ;                                        );
  452.  ;
  453.  ;  XMSmemError is returned if the operation fails, Zero if success.
  454.  ;
  455.  
  456. procname  XMStoMem
  457.  
  458.         PUSH    BP
  459.         MOV     BP,SP
  460.  
  461.         PUSH    BX
  462.         PUSH    CX
  463.         PUSH    DX
  464.         PUSH    SI
  465.         PUSH    DI
  466.         PUSH    ES
  467.         PUSH    DS
  468.  
  469.         MOV     AX,CS                   ; Set Data Segment to Code Segment.
  470.         MOV     DS,AX                   ;
  471.  
  472.         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
  473.         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
  474.         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
  475.         MOV     [XMSmainGET.SrcHandle],DX ; Set it in the move structures.
  476.         MOV     [XMSwordGET.SrcHandle],DX ;
  477.  
  478.         XOR     DX,DX                   ;
  479.         MOV     DI,xmsgpblk[BP]         ; Get the block number.
  480.         SHR     DI,1                    ; Form the 32 bit XMS address in
  481.         RCR     DX,1                    ;  DI:DX.
  482.         SHR     DI,1                    ;
  483.         RCR     DX,1                    ;
  484.         ADD     DX,xmsgpblkAdr[BP]      ;
  485.  
  486.         TEST    CX,1                    ; Check for an odd number of bytes
  487.         JZ      XMStoMem02              ;  to transfer.
  488.  
  489.         DEC     CX                      ; Decrement to an even number of
  490. bytes.
  491.  
  492.         TEST    DX,1                    ; Check for an odd XMS address.
  493.         JZ      XMStoMem01              ;
  494.  
  495.                                         ; XMS address is odd.
  496.                                         ; -------------------
  497.         DEC     DX                      ;
  498.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  499.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  500.  
  501.         MOV     AH,0BH                  ; Set the XMS move, function code.
  502.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  503.  
  504.         PUSH    BX                      ;
  505.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  506.         POP     BX                      ;
  507.         DEC     AX                      ; Check for errors.
  508.         JNZ     XMStoMem03              ; Error out if error.
  509.  
  510.         MOV     AX,[XMSword]            ; Get the moved word.
  511.  
  512.         MOV     ES:[BX],AH              ; Move the odd byte to memory.
  513.  
  514.         INC     BX                      ; Reset the memory address.
  515.         ADD     DX,2                    ; And the XMS address.
  516.  
  517.         JMP     XMStoMem02              ; Move the block.
  518.  
  519.  
  520.   XMStoMem01:
  521.                                         ; XMS address is even.
  522.                                         ; --------------------
  523.         ADD     DX,CX                   ;
  524.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  525.         SUB     DX,CX                       ;
  526.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  527.  
  528.         MOV     AH,0BH                  ; Set the XMS move, function code.
  529.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  530.  
  531.         PUSH    BX                      ;
  532.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  533.         POP     BX                      ;
  534.         DEC     AX                      ; Check for errors.
  535.         JNZ     XMStoMem03              ; Error out if error.
  536.  
  537.         MOV     AX,[XMSword]            ; Get the moved word.
  538.  
  539.         XCHG    DI,CX                   ;
  540.         MOV     ES:[BX+DI],AL           ; Move the odd byte to memory.
  541.         XCHG    DI,CX                   ;
  542.  
  543.   XMStoMem02:
  544.         JCXZ    XMStoMem04              ; Avoid a zero byte move.
  545.  
  546.         MOV     XMSmainGET.Length,CX    ; Set length for the move.
  547.  
  548.         MOV     XMSmainGET.DestOffset,BX   ; Set Memory address.
  549.         MOV     XMSmainGET.DestOffsetX,ES  ;
  550.  
  551.         MOV     XMSmainGET.SrcOffset,DX    ; Set XMS address.
  552.         MOV     XMSmainGET.SrcOffsetX,DI   ;
  553.  
  554.         MOV     AH,0BH                  ; Set the XMS move, function code.
  555.         MOV     SI,OFFSET XMSmainGET    ; Set address of the move structure.
  556.  
  557.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  558.         DEC     AX                      ; Check for errors.
  559.         JZ      XMStoMem05
  560.  
  561.   XMStoMem03:
  562.         MOV     AX,XMSmemError          ; Set error code if error.
  563.         JMP     XMStoMem05              ;
  564.  
  565.   XMStoMem04:
  566.         XOR     AX,AX                   ;
  567.  
  568.   XMStoMem05:
  569.         POP     DS
  570.         POP     ES
  571.         POP     DI
  572.         POP     SI
  573.         POP     DX
  574.         POP     CX
  575.         POP     BX
  576.  
  577.         POP     BP
  578.         RET                             ; Exit
  579.  
  580. endproc  XMStoMem
  581.  
  582. SUBTTL  Extended Memory - MemToXMS
  583. PAGE+
  584.  
  585.  
  586.  ;
  587.  ; Stack frame definition for int MemToXMS( unsigned Handle,
  588.  ;                                        unsigned blk,
  589.  ;                                        unsigned blkAdr,
  590.  ;                                        unsigned Bytes,
  591.  ;                                        char     *memAdr
  592.  ;                                       );
  593.  ;
  594.  ;  XMSmemError is returned if the operation fails, Zero if success.
  595.  ;
  596.  
  597. procname  MemToXMS
  598.  
  599.         PUSH    BP
  600.         MOV     BP,SP
  601.  
  602.         PUSH    BX
  603.         PUSH    CX
  604.         PUSH    DX
  605.         PUSH    SI
  606.         PUSH    DI
  607.         PUSH    ES
  608.         PUSH    DS
  609.  
  610.         MOV     AX,CS                   ;
  611.         MOV     DS,AX                   ;
  612.  
  613.         MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
  614.         LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
  615.         MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
  616.         MOV     [XMSmainPUT.DestHandle],DX ; Set it in the move structures.
  617.         MOV     [XMSwordPUT.DestHandle],DX ;
  618.         MOV     [XMSwordGET.SrcHandle],DX  ;
  619.  
  620.         XOR     DX,DX                   ;
  621.         MOV     DI,xmsgpblk[BP]         ; Get the block number.
  622.         SHR     DI,1                    ; Form the 32 bit XMS address in
  623.         RCR     DX,1                    ;  DI:DX.
  624.         SHR     DI,1                    ;
  625.         RCR     DX,1                    ;
  626.         ADD     DX,xmsgpblkAdr[BP]      ;
  627.  
  628.         TEST    CX,1                    ; Check for an odd number of bytes
  629.         JZ      MemToXMS02              ;  to transfer.
  630.  
  631.         DEC     CX                      ; Decrement to an even number of
  632. bytes.
  633.  
  634.         TEST    DX,1                    ; Check for an odd XMS address.
  635.         JZ      MemToXMS01              ;
  636.  
  637.                                         ; XMS address is odd.
  638.                                         ; -------------------
  639.         DEC     DX                      ;
  640.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  641.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  642.         MOV     [XMSwordPUT.DestOffset],DX  ;
  643.         MOV     [XMSwordPUT.DestOffsetX],DI ;
  644.  
  645.         MOV     AH,0BH                  ; Set the XMS move, function code.
  646.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  647.  
  648.         PUSH    BX                      ;
  649.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  650.         POP     BX                      ;
  651.         DEC     AX                      ; Check for errors.
  652.         JNZ     MemToXMS03              ; Error out if error.
  653.  
  654.         MOV     AH,ES:[BX]              ; Get the odd memory byte.
  655.  
  656.         MOV     [XMSwordByte+1],AH      ; Put it in the moved word.
  657.  
  658.         MOV     AH,0BH                  ; Set the XMS move, function code.
  659.         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
  660.  
  661.         PUSH    BX                      ;
  662.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  663.         POP     BX                      ;
  664.         DEC     AX                      ; Check for errors.
  665.         JNZ     MemToXMS03              ; Error out if error.
  666.  
  667.         INC     BX                      ; Reset the memory address.
  668.         ADD     DX,2                    ; And the XMS address.
  669.  
  670.         JMP     MemToXMS02              ; Move the block.
  671.  
  672.   MemToXMS01:
  673.                                         ; XMS address is even.
  674.                                         ; --------------------
  675.         ADD     DX,CX                   ;
  676.         MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
  677.         MOV     [XMSwordPUT.DestOffset],DX  ;
  678.         SUB     DX,CX                       ;
  679.         MOV     [XMSwordGET.SrcOffsetX],DI  ;
  680.         MOV     [XMSwordPUT.DestOffsetX],DI ;
  681.  
  682.         MOV     AH,0BH                  ; Set the XMS move, function code.
  683.         MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
  684.  
  685.         PUSH    BX                      ;
  686.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  687.         POP     BX                      ;
  688.         DEC     AX                      ; Check for errors.
  689.         JNZ     MemToXMS03              ; Error out if error.
  690.  
  691.         XCHG    DI,CX                   ;
  692.         MOV     AL,ES:[BX+DI]           ; Get the odd memory byte.
  693.         XCHG    DI,CX                   ;
  694.  
  695.         MOV     [XMSwordByte],AL        ; Set the moved word.
  696.  
  697.         MOV     AH,0BH                  ; Set the XMS move, function code.
  698.         MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
  699.  
  700.         PUSH    BX                      ;
  701.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  702.         POP     BX                      ;
  703.         DEC     AX                      ; Check for errors.
  704.         JNZ     MemToXMS03              ; Error out if error.
  705.  
  706.   MemToXMS02:
  707.         JCXZ    MemToXMS04              ; Avoid a zero byte move.
  708.  
  709.         MOV     XMSmainPUT.Length,CX    ; Set length for the move.
  710.  
  711.         MOV     XMSmainPUT.SrcOffset,BX    ; Set Memory address.
  712.         MOV     XMSmainPUT.SrcOffsetX,ES   ;
  713.  
  714.         MOV     XMSmainPUT.DestOffset,DX   ; Set XMS address.
  715.         MOV     XMSmainPUT.DestOffsetX,DI  ;
  716.  
  717.         MOV     AH,0BH                  ; Set the XMS move, function code.
  718.         MOV     SI,OFFSET XMSmainPUT    ; Set address of the move structure.
  719.  
  720.         CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
  721.         DEC     AX                      ; Check for errors.
  722.         JZ      MemToXMS05
  723.  
  724.   MemToXMS03:
  725.         MOV     AX,XMSmemError          ; Set error code if error.
  726.         JMP     MemToXMS05              ;
  727.  
  728.   MemToXMS04:
  729.         XOR     AX,AX                   ;
  730.  
  731.   MemToXMS05:
  732.         POP     DS
  733.         POP     ES
  734.         POP     DI
  735.         POP     SI
  736.         POP     DX
  737.         POP     CX
  738.         POP     BX
  739.  
  740.         POP     BP
  741.         RET                             ; Exit
  742.  
  743. endproc  MemToXMS
  744.  
  745.  
  746. SUBTTL  Last Page
  747. PAGE+
  748.  
  749. pwrlolvl_TEXT   ENDS
  750.  
  751.         END
  752.  
  753.